package roborally;

import be.kuleuven.cs.som.annotate.Basic;

/**
 * @version	3.0
 * @author 	Lies Tambeur 	r0264469	2Bcwsbbh
 * @author	Eline Vanrykel	r0264543	2Bcwselt
 */
public class Position {
	
	private long xCoord;
	private long yCoord;
	
	/**
	 * @param x
	 * @param y
	 * @effect | this.setX(x)
	 * @effect | this.setY(y)
	 */
	public Position(long x, long y){
		this.setX(x);
		this.setY(y);
	}
	
	/**
	 * @param x
	 * @post | new.getX() == x
	 */
	public void setX(long x){
		this.xCoord = x;
	}
	
	/**
	 * @param y
	 * @post | new.getY() == y
	 */
	public void setY(long y){
		this.yCoord = y;
	}
	
	/**
	 * @return | result == this.xCoord
	 */
	@Basic
	public long getX(){
		return xCoord;
	}
	
	/**
	 * @return | result == this.yCoord
	 */
	@Basic
	public long getY(){
		return yCoord;
	}
	
	/**
	 * @param 	orientation
	 * @return 	| result == new Position(this.getX()+1,this.getY() )
	 * 			|	|| result == new Position(this.getX()-1,this.getY()) 
	 * 			|	|| result == new Position(this.getX(),this.getY()+1) 
	 * 			| 	|| result == new Position(this.getX(),this.getY()-1)
	 */
	public Position getNeighbour(Orientation orientation){
		Position thePosition=new Position(this.getX(),this.getY());
		switch(orientation){
			case UP: thePosition.setY(this.getY()-1); break;
			case RIGHT: thePosition.setX(this.getX()+1); break; 
			case DOWN: thePosition.setY(this.getY()+1); break;
			case LEFT: thePosition.setX(this.getX()-1); break;
		}
		return thePosition; 
	}
	
	/**
	 * @param 	other
	 * @return | result == Math.sqrt(Math.pow(this.getX()-other.getX(),2)+Math.pow(this.getY()-other.getY(),2))
	 */
	public double getManhattanDistance(Position other){
		double x=Math.pow(this.getX()-other.getX(),2);
		double y=Math.pow(this.getY()-other.getY(),2);
		double distance = Math.sqrt(  x + y );
		return distance;
	}
	
	public boolean isNeighbour(Position position){
		for(Orientation orientation: Orientation.values()){
			if(this.getNeighbour(orientation).equals(position)){
				return true;
			}
		}
		return false;
	}
	
	/**
	 * @return 	| result == 31*(31+(this.getX()^(this.getX()>>>32)))+(this.getY()^(this.getY()>>>32))
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (int) (this.getX() ^ (this.getX() >>> 32));
		result = prime * result + (int) (this.getY() ^ (this.getY() >>> 32));
		return result;
	}
	
	/**
	 * @return 	| result == Position [xCoord=" + this.getX() + ", yCoord=" + this.getY() + "]
	 */
	@Override
	public String toString() {
		return "(" + this.getX() + ", " + this.getY() + ")";
	}

	/**
	 * @return 	| if (obj == null || this.getClass != obj.getClass() || this.getX() != obj.getX() || this.getY() != obj.getY())
	 * 			|	then result == false
	 * 			| else  result == true
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Position other = (Position) obj;
		if (this.getX() != other.getX())
			return false;
		if (this.getY() != other.getY())
			return false;
		return true;
	}	
}
